{***************************************************************
    SpyGestion  Copyright (C) 2008 Christophe KOALI <nature2gas@gmail.com>
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
****************************************************************}
unit modFlotteEnVoyage;

interface

uses Classes, SysUtils, modBaseType;

type
   TFlotteVoyageMission = (fvmNeant);
   

   TFlotteListEnVoyage = record
      Numero   : integer;
      Mission  : TOGOrdre;
      Direction: TOGDirection;

      // Informations sur les vaisseaux et ce qu'ils transportent
      Nombre   : integer;
      Vaisseaux: string;
      Ressource: TOGRessourceAll;

      Depart     : TPlanetLocation;
      DepartDate : int64;                     // Date Serveur

      Arrivee    : TPlanetLocation;
      ArriveeDate: int64;                     // Date Serveur

      // hash de location Depart et Arrivee
      HashDepartArrivee: int64;

      // Données à poster pour faire revenir la flotte
      ReturnDataToPost: string;
      ReturnDataURL   : string;
   end;


    PFlotteListEnVoyage = ^TFlotteListEnVoyage;
    TCollectionFlotteListEnVoyage = class(TList)
    private
       {--------------------------------------------------}
       {Elements spécialisés de la classes}
       

       {--------------------------------------------------}
       {Gestion des pointeurs}
       // Utilisé pour la propriété Itemx
       function GetItemx(Index: integer): TFlotteListEnVoyage;
    public
       // Renvoi la date de la première flotte qui rentre à quai
       // cela permettra de savoir quand une flotte va se libérer
       // Sinon renvoi -1
       function GetDateFirstRetour: int64;


       // Renvoi la date du premier impact OU de la première flotte qui rentre à quai
       // en effet, avec GetDateFirstRetour, il se peut qu'une flotte "rapide"
       // soit encore dans le sens aller, mais soit la première à retourner à quai
       // alors qu'en parallèle il y a déjà une flotte sur le chemin du retour
       function GetDateFirstImpact: int64;

       {--------------------------------------------------}
       {Gestion des pointeurs}
       // *** Ajout de pointeurs
       // Renvoi le pointeur de l'élément ajouté
       function Add(Element: TFlotteListEnVoyage): PFlotteListEnVoyage;
      
       // Simple ajout de pointeur
       procedure SimpleAdd(Pointeur: PFlotteListEnVoyage);
      
       // Renvoi le pointeur de l'élément ajouté/modifié
       // Utilise Get_Index pour vérifier si l'élément doit être mis à jour
       function Add_Update(Element: TFlotteListEnVoyage): PFlotteListEnVoyage;
      
      
       // *** Suppression de pointeur
       // Libère et supprime le pointeur Index
       // Renvoi True si réussit, False si hors limite ou erreur
       function Delete(Index: integer): boolean; 

      
       // *** Effacement de la liste de pointeur
       procedure Clear; override;
      
      
       // *** Requete sur la liste de pointeur
       function Get_Index(const Element: integer): integer;
       function Get_Pointeur(const Element: integer): PFlotteListEnVoyage;
       function Get_Item(Index: integer): TFlotteListEnVoyage;
       property Itemx[Index: integer]: TFlotteListEnVoyage read GetItemx;


       function GetFromUID(puid: PFlotteOwnUID): PFlotteListEnVoyage;

       procedure SetURLOfPage(PageWeb: string);

       {--------------------------------------------------}
       {Procédures et fonctions spécialisées de la classes}
       // Destructeur
       destructor Destroy; override;
       constructor Create;

    end;


implementation

uses sHTMLFonctions, modAlarmeAttaque;


{*******************************************************************************
 ******************************************************************************* 
 **               TCollectionFlotteListEnVoyage                                     **
 *******************************************************************************
 *******************************************************************************}

procedure TCollectionFlotteListEnVoyage.SetURLOfPage(PageWeb: string);
var i: integer;
    pElement: PFlotteListEnVoyage;
begin

    if Count = 0 then begin
       exit;
    end;

    for i := 0 to Count - 1 do begin
       pElement := Items[i];

       if pElement.ReturnDataURL <> '' then begin
          // on peut rappeller la flotte
          pElement.ReturnDataURL := sHTML_Get_URL_Lien(PageWeb, pElement.ReturnDataURL);
       end;

       pElement.HashDepartArrivee := hashCalculDepartArrivee(pElement.Depart, pElement.Arrivee);

    end;

end;


constructor TCollectionFlotteListEnVoyage.Create;
begin
    
    // Héritage
    InHerited Create;
    
    
    
    // Code pour l'initialisation ici
    
    
end;

destructor TCollectionFlotteListEnVoyage.Destroy;
begin
    // Implémenter le code avant l'héritage de la méthode
    // C'est à dire ici
    
   
    // On appelle NOTRE clear qui lui-même appelle NOTRE Delete qui libère l'espace mémoire
    // avant d'enlever le pointeur de la TList
    // L'héritage de Destroy appelle Clear, mais es-ce le notre ou celui de la classe de base ?
    Clear;
    
    
    // Héritage
    InHerited Destroy;
end;


procedure TCollectionFlotteListEnVoyage.Clear;
var i: integer;
begin

    if Count > 0 then begin
        For i := Count -1 downto 0 do
            Delete(i);
    end;
    
    inherited Clear;
end;


function TCollectionFlotteListEnVoyage.Get_Pointeur(const Element: integer): PFlotteListEnVoyage;
var i: integer;
begin

   Result := nil;
   
   i := Get_Index(Element);
   if i < 0 then exit;
   Result := Items[i];

end;



function TCollectionFlotteListEnVoyage.GetDateFirstImpact: int64;
var i: integer;
    pElement: PFlotteListEnVoyage;
begin

    Result := -1;

   if Count <= 0 then exit;


   for i := 0 to Count - 1 do begin
      pElement := Items[i];


      // peu importe le sens, on prend la date qui a le premier impact
      if (Result < 0) or (pElement.ArriveeDate < Result) then
         Result := pElement.ArriveeDate

   end;

end;

function TCollectionFlotteListEnVoyage.GetDateFirstRetour: int64;
var i: integer;
    pElement: PFlotteListEnVoyage;
begin

    Result := -1;

   if Count <= 0 then exit;

   for i := 0 to Count - 1 do begin
      pElement := Items[i];

      if pElement.Direction = odRetour then begin
         // Flotte en retour
         if (Result < 0) or (pElement.ArriveeDate < Result) then
            Result := pElement.ArriveeDate

      end;

   end;


end;

function TCollectionFlotteListEnVoyage.GetFromUID(puid: PFlotteOwnUID): PFlotteListEnVoyage;
var
  i: Integer;
  pElement: PFlotteListEnVoyage;
begin
    Result := nil;

    if Count <= 0 then begin
       exit;
    end;

    for i := 0 to Count - 1 do begin
       pElement := Items[i];

       if (pElement.HashDepartArrivee = puid.Location) and (pElement.DepartDate = puid.DateDepart) then begin
          // c'est bon
          Result := pElement;
          exit;
       end;
    end;

end;

function TCollectionFlotteListEnVoyage.Get_Index(const Element: integer): integer;
var i: integer;
    pElement: PFlotteListEnVoyage;
begin

   Result := -1;

   if Count <= 0 then exit;

   for i := 0 to Count - 1 do begin
      pElement := Items[i];

      {### ### ### ### ### ### ### ### ### ### ### ### ### ### }
      {### Neccessite adpation en fonction du type record  ### }
      {### ### ### ### ### ### ### ### ### ### ### ### ### ### }

      if pElement^.Numero = Element then begin
         Result := i;
         exit;
      end;
   end;

end;



function TCollectionFlotteListEnVoyage.Add_Update(Element: TFlotteListEnVoyage): PFlotteListEnVoyage;
var i : integer;
begin
     
     Result := nil;
                                         {### ### ### ### ### ### ### ### ### ### ### ### ### ### }
     i := Get_Index(Element.Numero);        {### Neccessite adpation en fonction du type record  ### }
                                         {### ### ### ### ### ### ### ### ### ### ### ### ### ### }
     if i < 0 then begin 
        // L'élément n'existe pas, l'ajoute
        Result  := Add(Element);
     end else begin
        // L'élément existe déjà, le met à jour
        Result  := Items[i];     // Obtient le pointeur
        Result^ := Element;
     end;
     
end;




function TCollectionFlotteListEnVoyage.Get_Item(Index: integer): TFlotteListEnVoyage;
var pElement: PFlotteListEnVoyage;
begin

     if Index < 0 then exit;
     if Index >= Count then exit;

     pElement := Items[Index];     // Obtient le pointeur
     Result := pElement^;

end;

function TCollectionFlotteListEnVoyage.Delete(Index: integer): boolean;
var pElement: PFlotteListEnVoyage;
begin

    Result := false;

    if (Index < 0) or (Index >= Count) then
       // Hors limite
       exit;


    // Obtient le pointeur
    pElement := Items[Index];

    if pElement <> nil then
       // Libére la mémoire créée lors de l'ajout
       Dispose(pElement);

    // Supprime le pointeur de la liste
    inherited Delete(Index);

    // Met le resultat à True
    Result := true;

end;


function TCollectionFlotteListEnVoyage.Add(Element: TFlotteListEnVoyage): PFlotteListEnVoyage;
var pElement: PFlotteListEnVoyage;
begin
    
    Result := nil;
    
    New(pElement);          // Créer l'espace mémoire requis
    pElement^ := Element;   // Recopie les données dans l'emplacement pointé
    
    try
       inherited Add(pElement);  // Ajoute le pointeur à la liste
       Result := pElement;
    except
       Result := nil;
    end;
    
    // Pour libérer la mémoire occupé par l'élément pointer:  Dispose(pElement);

end;

// Simple ajout de pointeur
procedure TCollectionFlotteListEnVoyage.SimpleAdd(Pointeur: PFlotteListEnVoyage);
begin
    
    inherited Add(Pointeur);  // Ajoute le pointeur à la liste
    
end;

function TCollectionFlotteListEnVoyage.GetItemx(Index: integer): TFlotteListEnVoyage;
var pElement: PFlotteListEnVoyage;
begin

   if Count < 0 then exit;
   if Index >= Count then exit;

   pElement := Items[Index];
   Result := pElement^;

end;



end.
